/*
 * @(#)DocumentContentTransformer.java
 * Date 2013-04-11
 * Version 1.0
 * Author Jim Horner
 * Copyright (c)2012
 */


package us.hornerscorners.lamppost.repository.transformer.model;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.inject.Inject;

import ihe.iti.xds_b._2007.ProvideAndRegisterDocumentSetRequestType;

import ihe.iti.xds_b._2007.ProvideAndRegisterDocumentSetRequestType.Document;

import oasis.names.tc.ebxml_regrep.xsd.lcm._3.SubmitObjectsRequest;

import oasis.names.tc.ebxml_regrep.xsd.rim._3.ExtrinsicObjectType;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;

import us.hornerscorners.lamppost.exception.ServiceActionError;
import us.hornerscorners.lamppost.exception.ServiceActionException;
import us.hornerscorners.lamppost.exception.SeverityType;
import us.hornerscorners.lamppost.exception.ValidationException;

import us.hornerscorners.lamppost.model.document.DocumentContent;
import us.hornerscorners.lamppost.model.document.DocumentEntry;

import us.hornerscorners.lamppost.registry.constant.ErrorCode;
import us.hornerscorners.lamppost.registry.transformer.model.DocumentEntryTransformer;

import us.hornerscorners.lamppost.registry.utils.XDSUtils;

import us.hornerscorners.lamppost.transformer.AbstractTransformer;

import us.hornerscorners.lamppost.utils.OIDUtils;


/**
 * Class description
 *
 *
 * @version        v1.0, 2013-04-11
 * @author         Jim Horner
 */
public class DocumentContentTransformer
        extends AbstractTransformer<ProvideAndRegisterDocumentSetRequestType,
            Collection<DocumentContent>> {

    /** Field description */
    @Inject
    private DocumentEntryTransformer documentEntryTransformer;

    /**
     * Constructs ...
     *
     */
    public DocumentContentTransformer() {
        super();
    }

    /**
     * Method description
     *
     *
     * @param request
     *
     * @return
     *
     */
    @Override
    public Collection<DocumentContent> transform(
            ProvideAndRegisterDocumentSetRequestType request)
            throws ServiceActionException {

        List<DocumentContent> result = new ArrayList<>();

        SubmitObjectsRequest sor = request.getSubmitObjectsRequest();

        Map<String, ExtrinsicObjectType> extrinsicObjects =
            XDSUtils.createDocumentEntryMap(sor);

        Set<String> docsProvided = new HashSet<>();

        for (Document doc : request.getDocument()) {

            String key = doc.getId();

            if (docsProvided.add(key) == false) {

                String msg =
                    String.format("The document [%s] is attached more than once.", key);

                ServiceActionError error =
                    new ServiceActionError(
                        ErrorCode.XDSRepositoryMetadataError.getCode(), msg,
                        SeverityType.Error);

                throw new ValidationException(getErrorLocation(), error);
            }

            ExtrinsicObjectType eo = extrinsicObjects.get(key);

            if (eo != null) {

                result.add(transform(eo, doc));

            } else {

                String msg = String.format("The document [%s] is missing metadata.", key);

                ServiceActionError error =
                    new ServiceActionError(
                        ErrorCode.XDSMissingDocumentMetadata.getCode(), msg,
                        SeverityType.Error);

                throw new ValidationException(getErrorLocation(), error);
            }
        }

        List<String> keys = new ArrayList<>();

        keys.addAll(extrinsicObjects.keySet());
        keys.removeAll(docsProvided);

        if (keys.isEmpty() == false) {

            String msg =
                String.format(
                    "The following extrinsic objects are missing documents {%s}.",
                    StringUtils.join(keys, ", "));

            ServiceActionError error =
                new ServiceActionError(ErrorCode.XDSMissingDocument.getCode(), msg,
                                       SeverityType.Error);

            throw new ValidationException(getErrorLocation(), error);
        }

        return result;
    }

    /**
     * Method description
     *
     *
     * @param eo
     * @param doc
     *
     * @return
     *
     */
    public DocumentContent transform(ExtrinsicObjectType eo, Document doc)
            throws ServiceActionException {

        DocumentContent result = null;

        byte[] content = doc.getValue();

        if (ArrayUtils.isNotEmpty(content)) {

            result = new DocumentContent();

            DocumentEntry entry = this.documentEntryTransformer.transform(eo);

            // set to "primary key"
            result.setEntryURN(OIDUtils.createURN(entry.getUniqueId().getRoot()));

            result.setContent(content);
            result.setHash(entry.getHash());
            result.setMimeType(entry.getMimeType());
            result.setRepositoryId(entry.getRepositoryId());
            result.setSize(entry.getSize());
            result.setUniqueId(entry.getUniqueId());

        } else {

            String msg =
                String.format("The document [%s] does not contain content; size = 0.",
                              doc.getId());

            ServiceActionError error =
                new ServiceActionError(ErrorCode.XDSMissingDocument.getCode(), msg,
                                       SeverityType.Error);

            throw new ValidationException(getErrorLocation(), error);
        }

        return result;
    }
}
